package com.beemans.corekit.integration.admob;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.ads.mediation.admob.AdMobAdapter;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.ResponseInfo;
import com.google.android.gms.ads.admanager.AdManagerAdRequest;
import com.google.android.gms.ads.admanager.AdManagerAdView;

public class AbBannerAdWrapper {
    @NonNull
    private final AbBannerAdvertConfig advertConfig;
    @Nullable
    private ViewGroup advertContainer;
    @Nullable
    private AdManagerAdView adView;
    @Nullable
    private AbAdNetworkListener mNetworkListener;
    @Nullable
    private AbAdEventListener mEventListener;

    private boolean isLoadingAd = false;

    public boolean isAdvertReady() {
        return false;
    }

    public boolean isAdvertLoading() {
        return isLoadingAd;
    }

    public AbBannerAdWrapper(
            @NonNull ViewGroup advertContainer,
            @NonNull AbBannerAdvertConfig advertConfig
    ) {
        this.advertContainer = advertContainer;
        this.advertConfig = advertConfig;

        initAdvert();
    }

    private void initAdvert() {
        if (advertContainer == null) {
            return;
        }

        final Context context = advertContainer.getContext();

        adView = new AdManagerAdView(context);
        adView.setAdUnitId(advertConfig.getPlacementId());
        adView.setOnPaidEventListener(adValue -> {
            if (mEventListener != null) {
                mEventListener.onAdPaidEvent(getResponseInfo(), adValue);
            }
        });
        adView.setAdListener(new AdListener() {
            @Override
            public void onAdLoaded() {
                isLoadingAd = false;

                if (mNetworkListener != null) {
                    mNetworkListener.onAdLoaded();
                }
            }

            @Override
            public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                isLoadingAd = false;

                handleAdFailedToLoad(mNetworkListener, loadAdError.toString());
            }

            @Override
            public void onAdImpression() {
                if (mEventListener != null) {
                    mEventListener.onAdImpression(getResponseInfo());
                }
            }

            @Override
            public void onAdClicked() {
                if (mEventListener != null) {
                    mEventListener.onAdClicked(getResponseInfo());
                }
            }

            @Override
            public void onAdClosed() {
                if (mEventListener != null) {
                    mEventListener.onAdClosed(getResponseInfo());
                }
            }

            @Override
            public void onAdOpened() {
            }

            @Override
            public void onAdSwipeGestureClicked() {
            }
        });

        if (advertContainer.getVisibility() != View.VISIBLE) {
            advertContainer.setVisibility(View.VISIBLE);
        }

        advertContainer.post(() -> {
            if (adView != null && advertContainer != null) {
                final ViewParent viewParent = adView.getParent();
                if (viewParent instanceof ViewGroup) {
                    ((ViewGroup) viewParent).removeView(adView);
                }

                advertContainer.removeAllViews();
                advertContainer.addView(adView);

                final int advertWidth = advertContainer.getWidth();
                final int adWidthDp = (int) AbAdvertUtils.pxToDp(context, advertWidth);
                adView.setAdSize(AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, adWidthDp));
            }
        });
    }

    public void loadAd(
            @NonNull AbAdNetworkListener networkListener,
            @NonNull AbAdEventListener eventListener
    ) {
        if (advertContainer == null) {
            return;
        }
        advertContainer.post(() -> {
            if (adView == null) {
                return;
            }

            isLoadingAd = true;
            mNetworkListener = networkListener;
            mEventListener = eventListener;

            try {
                final AdManagerAdRequest.Builder builder = new AdManagerAdRequest.Builder();
                if (advertConfig.isCollapsible()) {
                    final Bundle bundle = new Bundle();
                    bundle.putString(AbAdvertConstants.BANNER_COLLAPSIBLE, AbAdvertConstants.BANNER_BOTTOM);
                    builder.addNetworkExtrasBundle(AdMobAdapter.class, bundle);
                }
                adView.loadAd(builder.build());
            } catch (Throwable throwable) {
                isLoadingAd = false;
                mNetworkListener = null;
                mEventListener = null;

                handleAdFailedToLoad(networkListener, throwable.getMessage());
            }
        });
    }

    public void destroy() {
        mNetworkListener = null;
        mEventListener = null;

        if (advertContainer != null) {
            advertContainer.removeAllViews();
            advertContainer = null;
        }
        if (adView != null) {
            final ViewParent viewParent = adView.getParent();
            if (viewParent instanceof ViewGroup) {
                ((ViewGroup) viewParent).removeView(adView);
            }
            try {
                adView.destroy();
            } catch (Throwable ignored) {
            }

            adView = null;
        }
    }

    private void handleAdFailedToLoad(
            @Nullable AbAdNetworkListener networkListener,
            @Nullable String loadAdError
    ) {
        if (networkListener != null) {
            networkListener.onAdFailedToLoad(loadAdError);
        }
    }

    @Nullable
    private ResponseInfo getResponseInfo() {
        return adView != null ? adView.getResponseInfo() : null;
    }
}